﻿using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;

namespace Najak
{
	public partial class Entity
	{
		public class SelectionManager
		{
			public List<Entity> SelectedEntities = new List<Entity>();
			public Scene Scene;
			public Point? MouseDownLocation;
			public Entity Owner;

			public SelectionManager(Scene scene, Entity owner)
			{
				Scene = scene;
				Owner = owner;
			}

			public void Draw()
			{
				// Draw Rectangle here
				if (MouseDownLocation != null)
				{
					Rectangle rect = _FindSelectionRectangle();
					Drawing.Shapes.Instance.DrawRectangle(rect, Color.Yellow, 2);
					rect.X -= 1;
					rect.Y -= 1;
					rect.Width += 3;
					rect.Height += 3;
					Drawing.Shapes.Instance.DrawRectangle(rect, Color.Black, 1);
					rect.X += 3;
					rect.Y += 3;
					rect.Width -= 6;
					rect.Height -= 6;
					Drawing.Shapes.Instance.DrawRectangle(rect, Color.Black, 1);
				}
			}

			private Rectangle _FindSelectionRectangle()
			{
				Point mp = InputHandler.Instance.MouseScreenLocation;
				int minX = Math.Min(mp.X, MouseDownLocation.Value.X);
				int maxX = Math.Max(mp.X, MouseDownLocation.Value.X);
				int minY = Math.Min(mp.Y, MouseDownLocation.Value.Y);
				int maxY = Math.Max(mp.Y, MouseDownLocation.Value.Y);
				Rectangle rect = new Rectangle(minX, minY, maxX - minX, maxY - minY);
				return rect;
			}

			public void Activate()
			{

				InputHandler.Instance.RegisterForMouseEvent(this, MouseEventTypes.ButtonClick, MouseButtons.Left, KeyboardModes.Normal, _HandleLeftClick);
				InputHandler.Instance.RegisterForMouseEvent(this, MouseEventTypes.ButtonDown, MouseButtons.Left, KeyboardModes.Normal, _HandleMouseDown);
				InputHandler.Instance.RegisterForMouseEvent(this, MouseEventTypes.ButtonUp, MouseButtons.Left, KeyboardModes.Normal, _HandleMouseUp);

			}
			public void DeActivate()
			{
				InputHandler.Instance.NotifyListenerRemoved(this);
			}

			private void _HandleMouseDown(MouseEvent evt)
			{
				MouseDownLocation = evt.ScreenLocation;
			}
			private void _HandleMouseUp(MouseEvent evt)
			{
				if (MouseDownLocation == null)
					return; // nothing to handle

				Rectangle rect = _FindSelectionRectangle();
				MouseDownLocation = null;

				if (evt.WasLeftClick)
					return; // click was activated

				if (rect.Width < Tile.HalfSize.X && rect.Height < Tile.HalfSize.Y)
					return; // not big enough for a selection

				int margin = 10;
				rect.X += -margin + (int)Scene.VportOffset.X;
				rect.Y += -margin + (int)Scene.VportOffset.Y;
				rect.Width += (2 * margin);
				rect.Height += (2 * margin);

				if (!InputHandler.Instance.IsCtrlPressed && !InputHandler.Instance.IsShiftPressed)
					ClearSelection();

				foreach (var e in Scene.Entities)
				{
					if (e.TeamID != Owner.TeamID && !App.IsEditorMode)
						continue;

					if (!e.IsSelectable)
						continue;

					Point loc = new Point((int)e.Location.X, (int)e.Location.Y);
					if (!rect.Contains(loc))
						continue;

					if (InputHandler.Instance.IsCtrlPressed)
					{
						if (e.IsSelected)
							_OnDeselected(e);
						else
							_OnSelected(e);
					}
					else
					{	// Shift or nothing
						_OnSelected(e);
					}
				}
			}

			private void _HandleLeftClick(MouseEvent evt)
			{
				if (Owner is PlayerEntity)
				{
					PlayerEntity player = Owner as PlayerEntity;
					if (player.IsWaitingLeftClick)
						return;
				}
				Entity entity = Scene.GetEntityAtCoordinate(evt.MapCoordinate);
				bool isAlreadySelected = (entity != null) && SelectedEntities.Contains(entity);

				if (entity != null && entity.TeamID != Owner.TeamID && !App.IsEditorMode)
					return;

				if (InputHandler.Instance.IsShiftPressed)
				{
					if (entity != null && !isAlreadySelected)
						_OnSelected(entity);
				}
				else if (InputHandler.Instance.IsCtrlPressed)
				{
					if (entity != null)
					{
						if (isAlreadySelected)
						{
							_OnDeselected(entity);
						}
						else
						{
							_OnSelected(entity);
						}
					}
				}
				else
				{
					ClearSelection();
					_OnSelected(entity);
				}
			}

			private void _OnSelected(Entity e)
			{
				if (e != null && !(e is Editor.GameEditorPlayer))
				{
					if (!SelectedEntities.Contains(e))
					{
						SelectedEntities.Add(e);
						e.OnSelected();
					}
				}
				if (EntitySelected != null)
					EntitySelected(this, e);
			}
			static public event Action<SelectionManager, Entity> EntitySelected;
			static public event Action<SelectionManager, Entity> EntityDeselected;

			private void _OnDeselected(Entity e)
			{
				if (e != null && SelectedEntities.Contains(e))
				{
					SelectedEntities.Remove(e);
					e.OnDeselected();
				}
				if (EntityDeselected != null)
					EntityDeselected(this, e);
			}

			public void ClearSelection()
			{
				for (int i = SelectedEntities.Count - 1; i >= 0; i--)
				{
					var e = SelectedEntities[i];
					_OnDeselected(e);
				}
			}
		}
	}
}
